#include <stdlib.h>
#include "Arbre.h"
#include "Symbole.h"
#include "SymboleValue.h"
#include "Valeur.h"

#include <sstream>  
#include <typeinfo> 
////////////////////////////////////////////////////////////////////////////////
NoeudSeqInst::NoeudSeqInst() : tabInst() {
    retour = NULL;
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudSeqInst::getValeur() {
    Valeur* val = NULL;
  for (unsigned int i=0; i<tabInst.size(); i++) {
    val = tabInst[i]->getValeur();  // on evalue chaque instruction de la séquence
  }
    if (retour!=NULL)
        val = retour->getValeur();
  return val; // par convention, resultat = valeur de la derniere instruction
}

////////////////////////////////////////////////////////////////////////////////
void NoeudSeqInst::afficher(unsigned short indentation) {
  Noeud::afficher(indentation);
  cout << "Noeud - Sequence de " << tabInst.size() << " instruction(s)" << endl;
  for (unsigned int i=0; i<tabInst.size(); i++)
    tabInst[i]->afficher(indentation+1); // on affiche les fils en augmentant l'indentation
}

////////////////////////////////////////////////////////////////////////////////
void NoeudSeqInst::ajouteInstruction(Noeud* instruction) {
  tabInst.push_back(instruction);
}
////////////////////////////////////////////////////////////////////////////////
/*string NoeudSeqInst::getCpp() {
    string code;
    for (unsigned int i=0;i < tabInst.size(); i++) 
    {
        code=code+tabInst[i]->getCpp(); 
      if (typeid(*tabInst[i])==typeid(NoeudFonction))
        code=code +";";
        code = code+"\n";
    }
    if (retour!=NULL)
        code=code + "return "+ retour->getCpp()+";";
    return code;
}
*/

////////////////////////////////////////////////////////////////////////////////
// NoeudFonction
////////////////////////////////////////////////////////////////////////////////

/*NoeudFonction::NoeudFonction(string nom,vector <LecteurFonction*> tf) : tabPar() {
    vector<LecteurFonction*>::iterator i;
      i=tf.begin();
  while (i<tf.end() && (**i).getNom() != nom) i++;
      if (i!=tf.end())
      setFonction(*i);
}
*/
////////////////////////////////////////////////////////////////////////////////
/*Valeur* NoeudFonction::getValeur() {
  return fonction->getValeur(tabPar);
}
*/
////////////////////////////////////////////////////////////////////////////////
/*void NoeudFonction::afficher(unsigned short indentation) {
  Noeud::afficher(indentation);
  cout << "Noeud - Fonction" << endl;
    Noeud::afficher(indentation);
    cout << "Nom : " << fonction->getNom() << endl;
        Noeud::afficher(indentation);
    cout << "nbParam : " << tabPar.size() << endl;   
    for (unsigned int i=0; i<tabPar.size();i++) {
     Noeud::afficher(indentation);
     if (typeid(*tabPar[i])==typeid(ValeurEntiere))
    cout << "Parametre " << i+1 << ", Type : entier, Valeur : " << ((ValeurEntiere*)tabPar[i])->getValeur() << endl;
     else if (typeid(*tabPar[i])==typeid(ValeurReelle))
    cout << "Parametre " << i+1 << ", Type : reel, Valeur : " << ((ValeurReelle*)tabPar[i])->getValeur() << endl;
     else if (typeid(*tabPar[i])==typeid(ValeurCaractere))
    cout << "Parametre " << i+1 << ", Type : caractere, Valeur : " << ((ValeurCaractere*)tabPar[i])->getValeur() << endl;
     else 
    cout << "Parametre " << i+1 << ", Type : chaine, Valeur : " << ((ValeurChaine*)tabPar[i])->getValeur() << endl;
    }
}

////////////////////////////////////////////////////////////////////////////////
void NoeudFonction::ajouteParametre(Noeud* exp) {

  tabPar.insert(tabPar.end(),exp);
  //push_back(val);
}
////////////////////////////////////////////////////////////////////////////////
string NoeudFonction::getCpp() {
    string code;
    std::ostringstream oss;

    code = code + fonction->getNom()+" (";
    if  (typeid(*tabPar[0])==typeid(ValeurEntiere))
            oss << ((ValeurEntiere*)tabPar[0])->getValeur();
    else if  (typeid(*tabPar[0])==typeid(ValeurReelle))
            oss << ((ValeurReelle*)tabPar[0])->getValeur();
    else if  (typeid(*tabPar[0])==typeid(ValeurCaractere))
            oss << ((ValeurCaractere*)tabPar[0])->getValeur();
    else 
            oss << (((ValeurChaine*)tabPar[0])->getValeur());  
    
    code += oss.str();
    oss.seekp(0);

    for (unsigned int i=1;i<tabPar.size();i++) {
        if  (typeid(*tabPar[i])==typeid(ValeurEntiere))
                oss << (((ValeurEntiere*)tabPar[i])->getValeur());
        else if  (typeid(*tabPar[i])==typeid(ValeurReelle))
                oss << (((ValeurReelle*)tabPar[i])->getValeur());
        else if  (typeid(*tabPar[i])==typeid(ValeurCaractere))
                oss << (((ValeurCaractere*)tabPar[i])->getValeur());
        else 
                oss << (((ValeurChaine*)tabPar[i])->getValeur());  
        code = code +","+ oss.str();
        oss.seekp(0);


    }
    code = code +")";
     return code;
}*/
////////////////////////////////////////////////////////////////////////////////
// NoeudAffectation
////////////////////////////////////////////////////////////////////////////////

NoeudAffectation::NoeudAffectation(Noeud* variable, Noeud* expression) {
  this->variable=variable;
  this->expression=expression;
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudAffectation::getValeur() {
    
  if (((SymboleValue*)variable)->estDefini())
        if (typeid(*((*variable).getValeur())) != typeid(*((*expression).getValeur())))
        {

            cout << "Affectation d'une valeur de mauvais type à la variable.\nType " 
                    << typeid(*((*variable).getValeur())).name() << " attendu, type "<< typeid(*((*expression).getValeur())).name() << " trouvé." <<  endl;
            exit(0);
        }
  Valeur* valeur = expression->getValeur(); // on évalue l'expression
  ((SymboleValue*)variable)->setValeur(valeur); // on affecte la variable
  return valeur; // par convention, une affectation a pour valeur la valeur affectée
}

////////////////////////////////////////////////////////////////////////////////
void NoeudAffectation::afficher(unsigned short indentation) {
  Noeud::afficher(indentation);
  cout << "Noeud - Affectation" << endl;
  variable->afficher(indentation+1);   // on affiche variable et expression
  expression->afficher(indentation+1); // en augmentant l'indentation
}
////////////////////////////////////////////////////////////////////////////////
//string NoeudAffectation::getCpp() {
//    
//    return ((SymboleValue*)variable)->getChaine()+" = "+expression->getCpp()+";";
//}

////////////////////////////////////////////////////////////////////////////////
// NoeudOperateurBinaire
////////////////////////////////////////////////////////////////////////////////

NoeudOperateurBinaire::NoeudOperateurBinaire ( Symbole operateur,
                                               Noeud* operandeGauche,
                                               Noeud* operandeDroit) {
  this->operateur=operateur;
  this->operandeGauche=operandeGauche;
  this->operandeDroit=operandeDroit;
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudOperateurBinaire::getValeur() { 
  if (this->operateur != "0") {
        Valeur* og=operandeGauche->getValeur();
        Valeur* od=operandeDroit->getValeur();
        if (typeid(*og)==typeid(ValeurEntiere) && typeid(*od)==typeid(ValeurEntiere))
        {
             if      (this->operateur=="+") return new ValeurEntiere(((ValeurEntiere*)og)->getValeur() + ((ValeurEntiere*)od)->getValeur()); 
             else if (this->operateur=="-") return new ValeurEntiere(((ValeurEntiere*)og)->getValeur() - ((ValeurEntiere*)od)->getValeur());
             else if (this->operateur=="*") return new ValeurEntiere(((ValeurEntiere*)og)->getValeur() * ((ValeurEntiere*)od)->getValeur()); 
             else if (this->operateur=="/")
                    if (((ValeurEntiere*)od)->getValeur() != 0)
                            return new ValeurEntiere(((ValeurEntiere*)og)->getValeur() / ((ValeurEntiere*)od)->getValeur());
                    else {
                            cout << "Erreur pendant l'interpretation : division par zero" << endl;
                            exit(0); //plus tard on levera une exception
                    }
             else if (this->operateur=="==")
                 return new ValeurEntiere(((ValeurEntiere*)og)->getValeur() == ((ValeurEntiere*)od)->getValeur());
             else if (this->operateur=="!=")
                 return new ValeurEntiere(((ValeurEntiere*)og)->getValeur() != ((ValeurEntiere*)od)->getValeur());
             else if (this->operateur=="<")
                 return new ValeurEntiere(((ValeurEntiere*)og)->getValeur() < ((ValeurEntiere*)od)->getValeur());
             else if (this->operateur=="<=")
                 return new ValeurEntiere(((ValeurEntiere*)og)->getValeur() <= ((ValeurEntiere*)od)->getValeur());
             else if (this->operateur==">")
                 return new ValeurEntiere(((ValeurEntiere*)og)->getValeur() > ((ValeurEntiere*)od)->getValeur());
             else if (this->operateur==">=")
                 return new ValeurEntiere(((ValeurEntiere*)og)->getValeur() >= ((ValeurEntiere*)od)->getValeur());
              else // this->operateur=="non"
                  return new ValeurEntiere(((ValeurEntiere*)od)->getValeur() ? 0 : 1);
        }
        else if (typeid(*og)==typeid(ValeurReelle) && typeid(*od)==typeid(ValeurReelle))
        {
            if      (this->operateur=="+") return new ValeurReelle(((ValeurReelle*)og)->getValeur() + ((ValeurReelle*)od)->getValeur()); 
             else if (this->operateur=="-") return new ValeurReelle(((ValeurReelle*)og)->getValeur() - ((ValeurReelle*)od)->getValeur());
             else if (this->operateur=="*") return new ValeurReelle(((ValeurReelle*)og)->getValeur() * ((ValeurReelle*)od)->getValeur()); 
             else if (this->operateur=="/")
                    if (((ValeurReelle*)od)->getValeur() != 0)
                            return new ValeurReelle(((ValeurReelle*)og)->getValeur() / ((ValeurReelle*)od)->getValeur());
                    else {
                            cout << "Erreur pendant l'interpretation : division par zero" << endl;
                            exit(0); //plus tard on levera une exception
                    }
             else if (this->operateur=="==")
                 return new ValeurEntiere(((ValeurReelle*)og)->getValeur() == ((ValeurReelle*)od)->getValeur());
             else if (this->operateur=="!=")
                 return new ValeurEntiere(((ValeurReelle*)og)->getValeur() != ((ValeurReelle*)od)->getValeur());
             else if (this->operateur=="<")
                 return new ValeurEntiere(((ValeurReelle*)og)->getValeur() < ((ValeurReelle*)od)->getValeur());
             else if (this->operateur=="<=")
                 return new ValeurEntiere(((ValeurReelle*)og)->getValeur() <= ((ValeurReelle*)od)->getValeur());
             else if (this->operateur==">")
                 return new ValeurEntiere(((ValeurReelle*)og)->getValeur() > ((ValeurReelle*)od)->getValeur());
             else if (this->operateur==">=")
                 return new ValeurEntiere(((ValeurReelle*)og)->getValeur() >= ((ValeurReelle*)od)->getValeur());
              else // this->operateur=="non"
              {
                 cout << "Erreur pendant l'interpretation : opérateur \"non\" utilisé sur une variable de type réel." << endl;
                 exit (0); //TODO : exception
              }
        }
            
        else if (typeid(*og)==typeid(ValeurChaine) && typeid(*od)==typeid(ValeurChaine))
        {
            if      (this->operateur=="+") {
                string og2 = ((ValeurChaine*)og)->getValeur();
                string od2 = ((ValeurChaine*)od)->getValeur();
                
                og2.erase(og2.end()-1);
                od2.erase(0,1);  //retrait des guillemets pour affichage propre
                
                return new ValeurChaine(og2 + od2); 
            }
             else if (this->operateur=="-") {
                            cout << "Erreur pendant l'interpretation : soustraction de deux chaînes" << endl;
                            exit(0); //plus tard on levera une exception
                    }
             else if (this->operateur=="*") {
                            cout << "Erreur pendant l'interpretation : multiplication de deux chaînes" << endl;
                            exit(0); //plus tard on levera une exception
                    }
             else if (this->operateur=="/"){
                            cout << "Erreur pendant l'interpretation : division de deux chaînes" << endl;
                            exit(0); //plus tard on levera une exception
                    }
             else if (this->operateur=="==")
                 return new ValeurEntiere(((ValeurChaine*)og)->getValeur() == ((ValeurChaine*)od)->getValeur());
             else if (this->operateur=="!=")
                 return new ValeurEntiere(((ValeurChaine*)og)->getValeur() != ((ValeurChaine*)od)->getValeur());
             else if (this->operateur=="<")
                 return new ValeurEntiere(((ValeurChaine*)og)->getValeur() < ((ValeurChaine*)od)->getValeur());
             else if (this->operateur=="<=")
                 return new ValeurEntiere(((ValeurChaine*)og)->getValeur() <= ((ValeurChaine*)od)->getValeur());
             else if (this->operateur==">")
                 return new ValeurEntiere(((ValeurChaine*)og)->getValeur() > ((ValeurChaine*)od)->getValeur());
             else if (this->operateur==">=")
                 return new ValeurEntiere(((ValeurChaine*)og)->getValeur() >= ((ValeurChaine*)od)->getValeur());
              else // this->operateur=="non"
                  {
                            cout << "Erreur pendant l'interpretation : opérateur \"non\" utilisé sur une variable de type chaîne" << endl;
                            exit(0); //plus tard on levera une exception
                  }
            
        }
            
        else if (typeid(*og)==typeid(ValeurCaractere) && typeid(*od)==typeid(ValeurCaractere))
        {
            if      (this->operateur=="+") return new ValeurCaractere(((ValeurCaractere*)og)->getValeur() + ((ValeurCaractere*)od)->getValeur()); 
             else if (this->operateur=="-") return new ValeurCaractere(((ValeurCaractere*)og)->getValeur() - ((ValeurCaractere*)od)->getValeur());
             else if (this->operateur=="*") return new ValeurCaractere(((ValeurCaractere*)og)->getValeur() * ((ValeurCaractere*)od)->getValeur()); 
             else if (this->operateur=="/")
                    if (((ValeurCaractere*)od)->getValeur() != 0)
                            return new ValeurCaractere(((ValeurCaractere*)og)->getValeur() / ((ValeurCaractere*)od)->getValeur());
                    else {
                            cout << "Erreur pendant l'interpretation : division par zero" << endl;
                            exit(0); //plus tard on levera une exception
                    }
             else if (this->operateur=="==")
                 return new ValeurCaractere(((ValeurCaractere*)og)->getValeur() == ((ValeurCaractere*)od)->getValeur());
             else if (this->operateur=="!=")
                 return new ValeurCaractere(((ValeurCaractere*)og)->getValeur() != ((ValeurCaractere*)od)->getValeur());
             else if (this->operateur=="<")
                 return new ValeurCaractere(((ValeurCaractere*)og)->getValeur() < ((ValeurCaractere*)od)->getValeur());
             else if (this->operateur=="<=")
                 return new ValeurCaractere(((ValeurCaractere*)og)->getValeur() <= ((ValeurCaractere*)od)->getValeur());
             else if (this->operateur==">")
                 return new ValeurCaractere(((ValeurCaractere*)og)->getValeur() > ((ValeurCaractere*)od)->getValeur());
             else if (this->operateur==">=")
                 return new ValeurCaractere(((ValeurCaractere*)og)->getValeur() >= ((ValeurCaractere*)od)->getValeur());
              else // this->operateur=="non"
                  return new ValeurCaractere(((ValeurCaractere*)od)->getValeur() ? 0 : 1);
            
        }
        else
        {
            cout << "Erreur pendant l'interprétation : opération sur des variables de types différents." /*<< operandeGauche->afficher() << " et " << operandeDroit->afficher() */<< endl;
            exit(0);
        }
            
        
  }
      
  return new ValeurEntiere(1);
 
}

////////////////////////////////////////////////////////////////////////////////
void NoeudOperateurBinaire::afficher(unsigned short indentation) {
  Noeud::afficher(indentation);
  cout << "Noeud - Operateur Binaire \"" << this->operateur.getChaine() << "\" applique a : " << endl;
  if (operandeGauche)
        operandeGauche->afficher(indentation+1);  // on affiche fils gauche et fils droit
  if (operandeDroit)
        operandeDroit->afficher(indentation+1);   // en augmentant l'indentation
}
////////////////////////////////////////////////////////////////////////////////
//string NoeudOperateurBinaire::getCpp() {
//    string op = operateur.getChaine();
//    string og = operandeGauche->getCpp();
//    string od = operandeDroit->getCpp();
//    if (operateur == "non")
//    {
//        og ="";
//        op ="!";
//        od ="("+od+")";
//    }
//        
//    return " "+og+" "+op+" "+od+" ";
//}
////////////////////////////////////////////////////////////////////////////////
Symbole* NoeudOperateurBinaire::getOp() {
    return &operateur;
}

////////////////////////////////////////////////////////////////////////////////
// NoeudInstSi
////////////////////////////////////////////////////////////////////////////////

void NoeudInstSi::afficher(unsigned short indentation) {
    Noeud::afficher(indentation);
    cout << "Noeud - Instruction Si " << endl;
    expBool->afficher(indentation+1);
    seqInst->afficher(indentation+1);
    if (sinon)
        sinon->afficher(indentation+1);
}

////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudInstSi::getValeur() {
    if (((ValeurEntiere*)expBool->getValeur())->getValeur())
        return seqInst->getValeur();
    else
    {
        if (sinon)
            return sinon->getValeur();
        else
            return (new NoeudSeqInst())->getValeur();
    }
}

////////////////////////////////////////////////////////////////////////////////
NoeudInstSi::NoeudInstSi(Noeud* expBool, Noeud* seqInst, NoeudInstSi* sinon) {
    this->expBool = expBool;
    this->seqInst = seqInst;
    this->sinon = sinon;    
}
////////////////////////////////////////////////////////////////////////////////
//string NoeudInstSi::getCpp() {
//    string codesi;
//    if(((NoeudOperateurBinaire*) expBool )->getOp()->getChaine()=="0")
//        codesi="{\n"+seqInst->getCpp()+"}\n";
//    else
//     codesi= "if ("+expBool->getCpp()+") \n{\n"+seqInst->getCpp()+"}\n";
//     if (sinon) {
//         codesi=codesi+"else "+sinon->getCpp();
//     }
//     return codesi;
//     //Sinon le fonctionne pas avec le transcodage, InstSi à refaire
//}

////////////////////////////////////////////////////////////////////////////////
// NoeudInstLoop
////////////////////////////////////////////////////////////////////////////////

NoeudInstLoop::NoeudInstLoop(Noeud* expBool, Noeud* seqInst){
    this->expBool = expBool;
    this->seqInst = seqInst;
}
////////////////////////////////////////////////////////////////////////////////

void NoeudInstLoop::afficher(unsigned short indentation,string message){
    Noeud::afficher(indentation);
    cout << message << endl;
    expBool->afficher(indentation+1);
    seqInst->afficher(indentation+1);
}


////////////////////////////////////////////////////////////////////////////////
// NoeudInstTantque
////////////////////////////////////////////////////////////////////////////////
NoeudInstTantque::NoeudInstTantque(Noeud* expBool, Noeud* seqInst) 
: NoeudInstLoop(expBool,seqInst){
}

////////////////////////////////////////////////////////////////////////////////
void NoeudInstTantque::afficher(unsigned short indentation) {
    NoeudInstLoop::afficher(indentation,"Noeud - Instruction Tant que");
}    
////////////////////////////////////////////////////////////////////////////////

Valeur* NoeudInstTantque::getValeur() {
    Valeur* valeur;
    while (((ValeurEntiere*)getCond()->getValeur())->getValeur())
        valeur = getSeq()->getValeur();
    
    return valeur;    
}
////////////////////////////////////////////////////////////////////////////////
/*string NoeudInstTantque::getCpp() {
    
    return "while ("+getCond()->getCpp()+") \n{ "+getSeq()->getCpp()+ "}";
}*/
////////////////////////////////////////////////////////////////////////////////
// NoeudInstRepeter
////////////////////////////////////////////////////////////////////////////////
NoeudInstRepeter::NoeudInstRepeter(Noeud* expBool, Noeud* seqInst) 
: NoeudInstLoop(expBool,seqInst){
}

////////////////////////////////////////////////////////////////////////////////
void NoeudInstRepeter::afficher(unsigned short indentation) {
    NoeudInstLoop::afficher(indentation,"Noeud - Instruction Repeter");
}    
////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudInstRepeter::getValeur() {
    Valeur* valeur;
    do
        valeur = getSeq()->getValeur();
    while (!((ValeurEntiere*)getCond()->getValeur())->getValeur());
    return valeur;    
}
////////////////////////////////////////////////////////////////////////////////
/*string NoeudInstRepeter::getCpp() {
    
    return "do \n{"+getSeq()->getCpp()+"} while (!"+getCond()->getCpp()+");";
}*/

////////////////////////////////////////////////////////////////////////////////
// NoeudInstPour
////////////////////////////////////////////////////////////////////////////////
NoeudInstPour::NoeudInstPour(Noeud* expBool, Noeud* seqInst,Noeud* init, Noeud* iter) 
: NoeudInstLoop(expBool,seqInst){
    this->init = init;
    this->iter = iter;
}

////////////////////////////////////////////////////////////////////////////////
void NoeudInstPour::afficher(unsigned short indentation) {
    NoeudInstLoop::afficher(indentation,"Noeud - Instruction Pour");
    init->afficher(indentation+1);
    iter->afficher(indentation+1);
}    
////////////////////////////////////////////////////////////////////////////////

Valeur* NoeudInstPour::getValeur() {
    Valeur* valeur;
    valeur = init->getValeur();
    while(((ValeurEntiere*)getCond()->getValeur())->getValeur())
    {
        getSeq()->getValeur();
        valeur = iter->getValeur();
    }
    return valeur;    
}
////////////////////////////////////////////////////////////////////////////////
/*string NoeudInstPour::getCpp() {
    string iteration = iter->getCpp();
    iteration.erase(iteration.end()-1);
    return "for ("+init->getCpp()+""+getCond()->getCpp()+";"+iteration+") { \n"+getSeq()->getCpp()+"}";
}
*/
////////////////////////////////////////////////////////////////////////////////
// NoeudInstLire
////////////////////////////////////////////////////////////////////////////////

NoeudInstLire::NoeudInstLire(Noeud* var) {
    this->var=var;
}
////////////////////////////////////////////////////////////////////////////////
void NoeudInstLire::afficher(unsigned short indentation) {
    Noeud::afficher(indentation);
    cout <<"Noeud - Instruction Lire " << endl;
    var->afficher(indentation+1);
}
////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudInstLire::getValeur() {
    
    if (!(*(SymboleValue*)var).estDefini())
    {
        cout << "Lecture d'une variable non typée : "/* << var->afficher() << "."*/ << endl;
        exit(0); //TODO : Exception
    }
    
    if (typeid(*var->getValeur())==typeid(ValeurEntiere))
    {
        int valeur;
        cin >> valeur;
        ((SymboleValue*)var)->setValeur(new ValeurEntiere(valeur));
    }
    if (typeid(*var->getValeur())==typeid(ValeurReelle))
    {
        float valeur;
        cin >> valeur;
        ((SymboleValue*)var)->setValeur(new ValeurReelle(valeur));
    }
    if (typeid(*var->getValeur())==typeid(ValeurChaine))
    {
        string valeur;
        cin >> valeur;
        valeur.insert(0,1,'"');
        valeur.insert(valeur.end(),1,'"');
        ((SymboleValue*)var)->setValeur(new ValeurChaine(valeur));
    }
    if (typeid(*var->getValeur())==typeid(ValeurCaractere))
    {
        char valeur;
        cin >> valeur;
        ((SymboleValue*)var)->setValeur(new ValeurCaractere(valeur));
    }
    return var->getValeur();
}
////////////////////////////////////////////////////////////////////////////////
/*string NoeudInstLire::getCpp() {
    
    return "cin >> "+var->getCpp()+";";
}*/

////////////////////////////////////////////////////////////////////////////////
// NoeudInstEcrire
////////////////////////////////////////////////////////////////////////////////

NoeudInstEcrire::NoeudInstEcrire(Noeud* var) {
    this->var=var;    
}
////////////////////////////////////////////////////////////////////////////////
void NoeudInstEcrire::afficher(unsigned short indentation) {
    Noeud::afficher(indentation);
    cout <<"Noeud - Instruction Ecrire " << endl;
    var->afficher(indentation+1);
}
////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudInstEcrire::getValeur() {
    
    if (typeid(*var->getValeur())==typeid(ValeurChaine))
    {
        string val = ((ValeurChaine*)var->getValeur())->getValeur();
        val.erase(0,1);  //retrait des guillemets pour affichage propre
        val.erase(val.end()-1);
         cout << val << endl;
    }
    else if (typeid(*var->getValeur())==typeid(ValeurEntiere))
         cout << ((ValeurEntiere*)var->getValeur())->getValeur() << endl;
    else if (typeid(*var->getValeur())==typeid(ValeurCaractere))
         cout << ((ValeurCaractere*)var->getValeur())->getValeur() << endl;
    else if (typeid(*var->getValeur())==typeid(ValeurReelle))
         cout << ((ValeurReelle*)var->getValeur())->getValeur() << endl;
    
    return NULL;
}
////////////////////////////////////////////////////////////////////////////////
/*string NoeudInstEcrire::getCpp() {
    
    return "cout << "+var->getCpp()+";";
}*/

////////////////////////////////////////////////////////////////////////////////
// NoeudInstSwitch
////////////////////////////////////////////////////////////////////////////////

NoeudInstSwitch::NoeudInstSwitch(Noeud* var) : tabCase()
{
    this->var=var;
}

////////////////////////////////////////////////////////////////////////////////
void NoeudInstSwitch::ajouteCase(NoeudInstCase* _case) {
  tabCase.push_back(_case);
}
////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudInstSwitch::getValeur() {
    unsigned int i = 0;
    if (typeid(*var->getValeur())==typeid(ValeurEntiere))
    {
    while (i<tabCase.size() && (((ValeurEntiere*)tabCase[i]->getVal())->getValeur() != ((ValeurEntiere*)var->getValeur())->getValeur()))
        ++i;
    
    if (i<tabCase.size())
        return tabCase[i]->getValeur();
    else
        return NULL;
    }
    else if (typeid(*var->getValeur())==typeid(ValeurReelle))
    {
    while (i<tabCase.size() && (((ValeurReelle*)tabCase[i]->getVal())->getValeur() != ((ValeurReelle*)var->getValeur())->getValeur()))
        ++i;
    
    if (i<tabCase.size())
        return tabCase[i]->getValeur();
    else
        return NULL;
    }
    else if (typeid(*var->getValeur())==typeid(ValeurChaine))
    {
    while (i<tabCase.size() && (((ValeurChaine*)tabCase[i]->getVal())->getValeur() != ((ValeurChaine*)var->getValeur())->getValeur()))
        ++i;
    
    if (i<tabCase.size())
        return tabCase[i]->getValeur();
    else
        return NULL;
    }
    else if (typeid(*var->getValeur())==typeid(ValeurCaractere))
    {
    while (i<tabCase.size() && (((ValeurCaractere*)tabCase[i]->getVal())->getValeur() != ((ValeurCaractere*)var->getValeur())->getValeur()))
        ++i;
    
    if (i<tabCase.size())
        return tabCase[i]->getValeur();
    else
        return NULL;
    }
    else
        return NULL;
}

////////////////////////////////////////////////////////////////////////////////
void NoeudInstSwitch::afficher(unsigned short indentation)
{
    Noeud::afficher(indentation);
    cout <<"Noeud - Instruction Switch " << endl;
    var->afficher(indentation+1);
    for (unsigned int i = 0; i < tabCase.size(); ++i)
        tabCase[i]->afficher(indentation+1);    
}
////////////////////////////////////////////////////////////////////////////////
//string NoeudInstSwitch::getCpp() {
//
//    string codeSwitch;
//    codeSwitch= "switch ("+var->getCpp()+")\n{";
//    for (unsigned int i = 0; i < tabCase.size(); ++i)
//                codeSwitch=codeSwitch+tabCase[i]->getCpp();
//    
//    codeSwitch += "}";
//    return codeSwitch;
//}

////////////////////////////////////////////////////////////////////////////////
// NoeudInstCase
////////////////////////////////////////////////////////////////////////////////

NoeudInstCase::NoeudInstCase(Noeud* val, Noeud* seqInst, bool def) {
    this->val = val;
    this->seqInst = seqInst;
    this->_default = def;
}
////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudInstCase::getVal() { //nécessaire pour évaluer la condition du switch
    return val->getValeur();
}
////////////////////////////////////////////////////////////////////////////////
Valeur* NoeudInstCase::getValeur() {
    return seqInst->getValeur();
}
////////////////////////////////////////////////////////////////////////////////
void NoeudInstCase::afficher(unsigned short indentation)
{
    Noeud::afficher(indentation);
    cout <<"Noeud - Instruction Case " << endl;
    val->afficher(indentation+1);
    seqInst->afficher(indentation+1);
}
////////////////////////////////////////////////////////////////////////////////
//string NoeudInstCase::getCpp() {
//    
//    if (!isDefault())
//         return "\tcase "+val->getCpp()+" : \n\t\t"+seqInst->getCpp()+"\t\tbreak;\n";
//    else 
//        return "\tdefault: \n\t\t"+seqInst->getCpp()+"\n";
//    
//    
//}
